import ConfigParser as cfg
import pdb
import pprint
import socket
import sys

# --------------------------------------------------------------------------
def contents(filename):
    f = open(filename)
    val = ''.join(f.readlines())
    f.close()
    return val

# --------------------------------------------------------------------------
def comma_list(value):
    """
    Split value at the commas, remove any quotations, and return a list.
    """
    rval = []
    for v in [x.strip() for x in value.split(',')]:
        if v[0] == '"':
            v = v.strip('"')
        elif v[0] == "'":
            v = v.strip("'")
        rval.append(v)
    return rval

# --------------------------------------------------------------------------
def which_member(clist, rsp):
    if rsp != '':
        for idx in range(0, len(clist)):
            if rsp in clist[idx]:
                return idx
    return -1

class Questionnaire:
    # ----------------------------------------------------------------------
    def __init__(self, filename=''):
        if filename != '':
            self.cf = cfg.SafeConfigParser()
            self.cf.read([filename])
            self.cf.set('DEFAULT', 'hostname', socket.gethostname())

    # ----------------------------------------------------------------------
    def pprint(self):
        for s in self.cf.sections():
            print("[%s]" % s)
            for o in self.cf.options(s):
                print("   %s = %s" % (o, self.cf.get(s, o)))

    # ----------------------------------------------------------------------
    def question(self, section):
        rval = {}
        rval['question'] = self.cf.get(section, 'question')
        rval['type'] = self.cf.get(section, 'type')
        if rval['type'] == 'text':
            try:
                rq = self.cf.get(section, 'required')
                if rq.lower() in ['1', 'true', 'yes', 'on']:
                    rval['required'] = True
                else:
                    rval['required'] = False
            except cfg.NoOptionError:
                rval['required'] = False
            rval['choices'] = None
        elif rval['type'] == 'choice':
            rval['choices'] = comma_list(self.cf.get(section, 'choices'))
            rval['required'] = None
        elif rval['type'] == 'stop':
            rval['choices'] = None
            rval['required'] = None

        try:
            rval['answer'] = self.cf.get(section, 'answer')
        except cfg.NoOptionError:
            rval['answer'] = None

        return rval
            
    # ----------------------------------------------------------------------
    def ask(self):
        k = self.cf.sections()
        k.sort()

        cur = start = k[0]
        while True:
            if cur == 'stop':
                break
            Q = self.question(cur)
            qn = self.cf.get(cur, 'question')
            qtype = self.cf.get(cur, 'type')
            print(Q['question'])
            if Q['answer'] != None:
                prompt = "[%s] > " % Q['answer']
            else:
                prompt = "> "
                
            if Q['type'] == 'text':
                rsp = raw_input(prompt)
                if rsp != '':
                    self.cf.set(cur, 'answer', rsp)
                cur = self.pick_next(cur, rsp)
            elif Q['type'] == 'choice':
                clist = Q['choices']
                rsp = ''
                idx = which_member(clist, rsp)
                while idx < 0:
                    if rsp != '':
                        print("'%s' is not an option" % rsp)
                    print("Choose one of "
                          + "(any non-empty substring will match):")
                    for c in clist:
                        print("   %s" % c)
                    rsp = raw_input(prompt)
                    if rsp == '' and Q['answer'] != None:
                        rsp = Q['answer']
                    idx = which_member(clist, rsp)
                self.cf.set(cur, 'answer', clist[idx])
                cur = self.pick_next(cur, clist[idx])
            elif Q['type'] == 'stop':
                break
            else:
                raise StandardError("Invalid question type '%s'" %
                                    self.qdict[cur]['type'])
        return self.cf

    # ----------------------------------------------------------------------
    def confirm(self):
        slist = self.cf.sections()
        slist.sort()
        print("----------------- Confirmation ---------------------")
        for s in slist:
            if self.cf.has_option(s, 'answer'):
                q = self.cf.get(s, 'question')
                a = self.cf.get(s, 'answer')
                print("Question %s: %s" % (s, q))
                print(" ")
                print('>>> %s' % a)
                print(" ")
        print("Please review your responses. "
              + "Is this the metadata you want to send?")
        c = raw_input("> ")
        if c.lower() == 'yes':
            return True
        else:
            return False
        
    # ----------------------------------------------------------------------
    def pick_next(self, sect, rsp):
        cf = self.cf
        try:
            nq = cf.get(sect, 'nextq')
        except cfg.NoOptionError:
            slist = cf.sections()
            slist.sort()
            idx = slist.index(sect) + 1
            if len(slist) <= idx:
                rval = 'stop'
            else:
                rval = slist[idx]
            return rval
        
        if ',' in nq:
            nqlist = comma_list(nq)
            choices = comma_list(cf.get(sect, 'choices'))
            idx = choices.index(rsp)
            if idx < 0:
                raise StandardError("Invalid reponse '%s'. " % rsp
                                    + "One of %s was expected" % choices)
            rval = nqlist[idx]
        else:
            rval = nq

        return rval

    # ----------------------------------------------------------------------
    def save(self, filename):
        f = open(filename, 'w')
        slist = self.cf.sections()
        slist.sort()
        for s in slist:
            f.write("[%s]\n" % s)
            for opt in self.cf.options(s):
                f.write("%s = %s\n" % (opt, self.cf.get(s, opt)))
        f.close()
